/*
 * © 2019 Copyright. Powered by Hongsheng Wu.
 */

package com.gl.basis.common.log;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 日志打印工具
 */
@Slf4j
public class LogUtil {
	/**
	 * 打印info日志
	 * @param title 标题
	 * @param msg  信息
	 */
	public static void info(String title, String msg) {

		StringBuffer sb = null;
		try {
			sb = baseinfo(title, msg);
		} catch (Exception ex) {
			log.info("日志记录出错,原始日志信息: [title : {} , msg : {},],日志记录异常原因: {}", title, msg,
					formatException(ex, new StringBuffer()));
			return;
		}
		log.info(sb.toString());
	}

	/**
	 * 打印warn日志
	 * @param title 标题
	 * @param msg  信息
	 */
	public static void warn(String title, String msg) {

		StringBuffer sb = null;
		try {
			sb = baseinfo(title, msg);
		} catch (Exception ex) {
			log.error("日志记录出错,原始日志信息: [title : {} , msg : {},],日志记录异常原因: {}", title, msg,
					formatException(ex, new StringBuffer()));
			return;
		}
		log.warn(sb.toString());
	}

	/**
	 * 打印error日志
	 * @param title 标题
	 * @param msg  信息
	 * @param e
	 */
	public static void error(String title, String msg, Exception e) {
		StringBuffer sb = null;
		try {
			sb = baseinfo(title, msg);
		} catch (Exception ex) {

			formatException(ex, sb);
			log.info("日志记录出错,原始日志信息: [title : {} , msg : {},exception : {}],日志记录异常原因: {}", title, msg,
					formatException(e, new StringBuffer()), formatException(e, new StringBuffer()));
			return;
		}
		if (e != null) {
			formatException(e, sb);
		}
		log.error(sb.toString());
	}

	/**
	 * 打印error日志
	 * @param title 标题
	 * @param msg  信息
	 */
	public static void error(String title, String msg) {
		error(title, msg, null);
	}

	private static String formatException(Exception e, StringBuffer sb) {
		sb.append("\r\n");
		sb.append(
				"	异常信息:  " + (e.getMessage().length() > 1024 ? e.getMessage().substring(0, 1024) : e.getMessage()));
		sb.append("\r\n");
		sb.append("	异常堆栈:  [");
		sb.append("\r\n");
		StackTraceElement[] stackArray = e.getStackTrace();
		for (int i = 0; i < stackArray.length; i++) {
			StackTraceElement element = stackArray[i];
			sb.append("		" + element.toString());
			sb.append("\r\n");
		}
		sb.append("	]");
		return sb.toString();
	}

	/**
	 * 基础信息
	 * @param title
	 * @param msg
	 */
	private static StringBuffer baseinfo(String title, String msg) {
		StringBuffer sb = new StringBuffer();
		try {
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getRequest();
			sb.append("\r\n");
			sb.append("	ip: ").append(getIpAddress(request)).append("\r\n");
			//			Object obj = SessionUtil.getSession().getAttribute(SessionUtil.CURRENT_USER);
			//			sb.append("\r\n");
			//			if (obj == null) {
			//				sb.append("	用户:  匿名用户");
			//			} else {
			//				sb.append("	用户:  ").append(((ASysUser) obj).getLoginName());
			//			}
			//			sb.append("\r\n");
			//			sb.append("	ip: ").append(SessionUtil.getClientIP()).append("\r\n");
			StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[3];
			//			if (Class.forName(stackTrace.getClassName()).isAnnotationPresent(Controller.class)) {
			//				sb.append("	URL: ").append(SessionUtil.getRequest().getRequestURI()).append("\r\n");
			//			}
//			sb.append("\r\n");
			sb.append("	类名: ").append(stackTrace.getClassName()).append("\r\n");
			sb.append("	方法名:").append(stackTrace.getMethodName()).append("\r\n");
			sb.append("	行数:").append(stackTrace.getLineNumber()).append("\r\n");
			sb.append("	标题:").append(title).append("\r\n");
			sb.append("	日志:");
			if (isJson(msg)) {
				sb.append(formatJson(msg));

			} else {
				sb.append(msg);
			}
		} catch (Exception e) {
			log.error("日志记录出错,原始日志信息: [title : {} , msg : {}],出错原因: {}", title, msg, e.getMessage());
		}
		return sb;
	}

	private static boolean isJson(String content) {

		try {
			JSONObject.parseObject(content);
			return true;
		} catch (Exception e) {
			return false;
		}

	}

	public static String formatJson(String jsonStr) {
		if (StringUtils.isEmpty(jsonStr)) {
			return " ";
		}
		jsonStr = jsonStr.replaceAll("\"", "").replaceAll("\\\"", "").replaceAll("\\\\", "");
		StringBuilder sb = new StringBuilder();
		char last = '\0';
		char current = '\0';
		int indent = 0;
		for (int i = 0; i < jsonStr.length(); i++) {
			last = current;
			current = jsonStr.charAt(i);
			switch (current) {
				case '{':
				case '[':
					sb.append(current);
					sb.append("\r\n");
					indent++;
					addIndentBlank(sb, indent);
					break;
				case '}':
				case ']':
					sb.append("\r\n");
					indent--;
					addIndentBlank(sb, indent);
					sb.append(current);
					break;
				case ',':
					sb.append(current);
					if (last != '\\') {
						sb.append("\r\n");
						addIndentBlank(sb, indent);
					}
					break;
				default:
					sb.append(current);
			}
		}
		return sb.toString();
	}

	private static void addIndentBlank(StringBuilder sb, int indent) {
		for (int i = 0; i < indent; i++) {
			sb.append("	");
		}
	}


	private static String getIpAddress(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

}
